在Java中执行Shell命令

您所在的位置:网站首页 java processbuilder执行shell脚本 在Java中执行Shell命令

在Java中执行Shell命令

2024-05-05 05:35| 来源: 网络整理| 查看: 265

介绍

在本文中,我们将研究如何利用Runtime和ProcessBuilder类来使用Java执行Shell命令和脚本。

我们使用计算机使日常工作中的许多事情自动化。 系统管理员一直在运行许多命令,其中一些命令重复性很强,并且每次运行之间的更改要求最少。

自动化的过程也已经成熟。 无需手动运行所有内容。 使用Java,我们可以运行单个或多个Shell命令,执行Shell脚本,运行终端/命令提示符,设置工作目录以及通过核心类操作环境变量。

Runtime.exec()

Java中的Runtime类是一个高级类,存在于每个Java应用程序中。 通过它,应用程序本身可以与其所在的环境进行通信。

通过getRuntime()方法提取与应用程序关联的运行时,我们可以使用exec()方法直接执行命令或运行.bat / .sh文件。

exec()方法提供了一些重载的变体:

public Process exec(String command)-在单独的进程中执行command中包含的命令。

public Process exec(String command, String[] envp)-使用环境变量数组执行command。 它们以字符串数组的形式提供,遵循name=value格式。

public Process exec(String command, String[] envp, File dir)-从dir目录中使用指定的环境变量执行command。

public Process exec(String cmdArray[])-以字符串数组的形式执行命令。

public Process exec(String cmdArray[], String[] envp)-使用指定的环境变量执行命令。

public Process exec(String cmdarray[], String[] envp, File dir)-从dir目录中使用指定的环境变量执行命令。

值得注意的是,这些过程是从解释器外部运行的,并且将取决于系统。

还值得注意的是String command和String cmdArray[]之间的区别。 他们达成了同样的目标。 无论如何,command都分解为一个数组,因此使用这两个中的任何一个应产生相同的结果。

您可以自行决定要使用exec("dir /folder")还是exec(new String[]{"dir","/folder"}。

让我们写一些示例,看看这些重载方法之间的区别。

从字符串执行命令

让我们从这三个中最简单的方法开始:

1Process process = Runtime.getRuntime().exec("ping www.stackabuse.com");

运行此代码将执行我们以字符串格式提供的命令。 但是,运行此命令时看不到任何东西。

为了验证它是否正确运行,我们将保留process对象。 让我们使用BufferedReader看看发生了什么:

1234567public static void printResults(Process process) throws IOException {     BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));     String line ="";     while ((line = reader.readLine()) != null) {         System.out.println(line);     } }

现在,当我们在exec()方法之后运行此方法时,它应该产生如下内容:

12345678910Pinging www.stackabuse.com [104.18.57.23] with 32 bytes of data: Reply from 104.18.57.23: bytes=32 time=21ms TTL=56 Reply from 104.18.57.23: bytes=32 time=21ms TTL=56 Reply from 104.18.57.23: bytes=32 time=21ms TTL=56 Reply from 104.18.57.23: bytes=32 time=21ms TTL=56 Ping statistics for 104.18.57.23:     Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds:     Minimum = 21ms, Maximum = 21ms, Average = 21ms

请记住,在浏览其他示例时,我们必须从Process实例中提取过程信息。

指定工作目录

如果您想从某个文件夹中运行命令,则可以执行以下操作:

1234Process process = Runtime.getRuntime()         .exec("cmd /c dir", null, new File("C:\\Users"));       //.exec("sh -c ls", null, new File("Pathname")); for non-Windows users printResults(process);

在这里,我们为exec()方法提供了command,用于新环境变量的null和被设置为工作目录的new File()。

值得注意的是,在诸如dir之类的命令之前添加了cmd /c。

由于我在Windows上工作,因此这会打开cmd,而/c会执行后续命令。 在这种情况下,它是dir。

SO用户很好地回答了为什么对于ping示例不是强制性的,但是对于此示例是强制性的。

运行前面的代码将导致:

123456789101112Volume in drive C has no label.  Volume Serial Number is XXXX-XXXX  Directory of C:\Users 08/29/2019  05:01 PM              . 08/29/2019  05:01 PM              .. 08/18/2016  09:11 PM              Default.migrated 08/29/2019  05:01 PM              Public 05/15/2020  11:08 AM              User                0 File(s)              0 bytes                5 Dir(s)  212,555,214,848 bytes free

让我们看一下如何在几个单独的部分而不是单个String中提供上一个命令:

123456Process process = Runtime.getRuntime().exec(         new String[]{"cmd","/c","dir"},         null,         new File("C:\\Users"));         printResults(process);

运行这段代码还将导致:

123456789101112Volume in drive C has no label.  Volume Serial Number is XXXX-XXXX  Directory of C:\Users 08/29/2019  05:01 PM              . 08/29/2019  05:01 PM              .. 08/18/2016  09:11 PM              Default.migrated 08/29/2019  05:01 PM              Public 05/15/2020  11:08 AM              User                0 File(s)              0 bytes                5 Dir(s)  212,542,808,064 bytes free

最终,无论采用哪种方法-使用单个String或String数组,您输入的命令在被基础逻辑处理之前,总是会分解成一个数组。

您想使用哪一个归结为您更易读。

使用环境变量

让我们看一下如何使用环境变量:

12345Process process = Runtime.getRuntime().exec(        "cmd /c echo %var1%",         new String[]{"var1=value1"});         printResults(process);

我们可以在String数组中提供任意数量的环境变量。 在这里,我们只是使用echo打印了var1的值。

运行此代码将返回:

1value1 运行.bat和.sh文件

有时,将所有内容卸载到文件中并运行该文件要比以编程方式添加所有内容容易得多。

根据您的操作系统,您将使用.bat或.sh文件。 让我们用内容创建一个:

1echo Hello World

然后,让我们使用与以前相同的方法:

1234Process process = Runtime.getRuntime().exec(        "cmd /c start file.bat",         null,         new File("C:\\Users\\User\\Desktop"));

这将打开命令提示符,并在我们设置的工作目录中运行.bat文件。

肯定地运行此代码会导致:

在处理了所有重载的exec()签名后,让我们看一下ProcessBuilder类以及如何使用它执行命令。

流程构建器

ProcessBuilder是使用Runtime.getRuntime().exec()方法时运行命令的基础机制:

1234567891011/**  * Executes the specified command and arguments in a separate process with  * the specified environment and working directory.  *... */ public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException {     return new ProcessBuilder(cmdarray)         .environment(envp)         .directory(dir)         .start(); }

Runtime类的JavaDocs small>

看一下ProcessBuilder如何从exec()方法获取我们的输入并运行命令,也使我们对如何使用它有了一个很好的了解。

它接受String[] cmdarray,足以使其运行。 另外,我们可以为其提供可选参数,例如String[] envp和File dir。

让我们探索这些选项。

ProcessBuilder:从字符串执行命令

在这种情况下,我们必须将其分解,而不是能够提供单个字符串,例如cmd /c dir。 例如,如果我们想像以前一样在C:/Users目录中列出文件,则可以这样做:

12345ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command("cmd","/c","dir C:\\Users"); Process process = processBuilder.start(); printResults(process);

要实际执行Process,我们运行start()命令并将返回的值分配给Process实例。

运行此代码将产生:

123456789101112 Volume in drive C has no label.  Volume Serial Number is XXXX-XXXX  Directory of C:\Users 08/29/2019  05:01 PM              . 08/29/2019  05:01 PM              .. 08/18/2016  09:11 PM              Default.migrated 08/29/2019  05:01 PM              Public 05/15/2020  11:08 AM              User                0 File(s)              0 bytes                5 Dir(s)  212,517,294,080 bytes free

但是,这种方法并没有比以前的方法更好。 ProcessBuilder类的有用之处在于它是可自定义的。 我们可以以编程方式设置内容,而不仅仅是通过命令。

ProcessBuilder:指定工作目录

与其通过命令提供工作目录,不如通过编程方式进行设置:

1processBuilder.command("cmd","/c","dir").directory(new File("C:\\Users"));

在这里,我们将工作目录设置为与以前相同,但是我们将该定义移出了命令本身。 运行此代码将提供与上一个示例相同的结果。

ProcessBuilder:环境变量

使用ProcessBuilder的方法,可以很容易地以Map的形式检索环境变量列表。 设置环境变量也很容易,以便您的程序可以使用它们。

让我们获取当前可用的环境变量,然后添加一些变量供以后使用:

1234ProcessBuilder processBuilder = new ProcessBuilder(); Map environmentVariables  = processBuilder.environment(); environmentVariables.forEach((key, value) -> System.out.println(key + value));

在这里,我们将返回的环境变量打包为Map并在其上运行forEach()以将值打印到控制台。

运行此代码将产生您在计算机上拥有的环境变量的列表:

1234DriverDataC:\Windows\System32\Drivers\DriverData HerokuPathE:\Heroku ProgramDataC:\ProgramData ...

现在,让我们向该列表添加一个环境变量并使用它:

12345environmentVariables.put("var1","value1"); processBuilder.command("cmd","/c","echo","%var1%"); Process process = processBuilder.start(); printResults(process);

运行此代码将产生:

1value1

当然,一旦程序完成运行,此变量将不会保留在列表中。

ProcessBuilder:运行.bat和.sh文件

再次,如果您想运行文件,我们将为ProcessBuilder实例提供所需的信息:

1234processBuilder         .command("cmd","/c","start","file.bat")         .directory(new File("C:\\Users\\User\\Desktop")); Process process = processBuilder.start();

运行此代码将导致打开命令提示符并执行.bat文件:

结论

在本文中,我们探讨了在Java中运行shell命令的示例。 我们已经使用Runtime和ProcessBuilder类来做到这一点。

使用Java,我们可以运行单个或多个Shell命令,执行Shell脚本,运行终端/命令提示符,设置工作目录以及通过核心类操作环境变量。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3